iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
0
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 10

Day10: Ruby中的Conditional Assignment Operator: x ||= y(or-equals)

  • 分享至 

  • xImage
  •  

最近的rails專案裡,看到了這行:

@cart = @cart || Cart.from_hash(session[:cart9527])

剛開始真的看不懂這段到底在幹嘛,為了想釐清觀念就查了一下資料,結果越查越多....而且方向還越來越偏XD

至於為什麼要特別寫這篇呢?我們已經知道Ruby中的等於是指派(Assign)的意思,那不就跟x += 1 等同於 x = x + 1而已嗎?


圖片來源

x ||= y 不是 x = x || y

難道這就是傳說中的Ruby界的WTF moment嗎?

那 x ||= y到底是什麼?

x ||= y

#expansion應該長
x || x = y 

If x is not initialized, false, nil or undefined, then evaluate y and set a to the result.

如果x尚未被初始化、false或nil及undefined,x 等於 y(換句話說:y會指派給x),其他情況下,x值不變。

所以:

@cart = @cart || Cart.from_hash(session[:cart9527])

#跟下面程式碼不相同

@cart ||= Cart.from_hash(session[:cart9527])

@cart現在是nil,第一圈會找Cart.from_hash(session[:cart9527])指派給@cart,第二圈因為@cart已經有值,故會將值指向自己。

再來看看幾個例子:

x被指派為nil或false

x = nil # 或 x = false
y = 10

puts x ||= y  # => x原本是nil,印出 x = 10

x被指派為2

x = 2
y = 10

puts x ||= y     # => x原本是2,印出 x = 2
puts x || x = y  # => 2
puts x = x || y  # => 2

剛剛才說,”x ||= y 不是 x = x || y“,那上面例子的第6行怎麼還會印出2?

竟然是曾經的熱門議題?

這個議題在約10年前討(爭)論(辯)的非常熱烈,可看下圖有人將所有的討論串做整理,最多有500多人在討論,有興趣的朋友可以點進去連結看看在吵些什麼XD

最噁心的討論就像這樣:

#sample1
a ||= b

#sample2
a || a = b

#sample3
a ? a : a = b

#sample4
if a then
  a 
else
  a = b 
end

#sample5
a = a || b

#sample6
a = a ? a : b

#sample7
if a then
  a = a 
else 
  a = b 
end

a || a = b, a ? a : a = b, if a then a else a = b end, and if a then a = a else a = b end will throw an error if a is undefined, whereas a ||= b and a = a || b will not. Also, a || a = b, a ? a : a = b, if a then a else a = b end, a = a ? a : b, and if a then a = a else a = b end evaluate a twice when a is truthy, whereas a ||= b and a = a || b do not.

看得我頭都暈了...且已經超過我能理解的範圍

總結:

x ||= y

If x is not initialized (or if it is set to nil or false), set it with the value of y.

如果x尚未被初始化、false或nil及undefined,則 x 等於 y (換句話說:y會指派給x),其他情況下,x值不變。

參考資料:
Conditional Assignment Operator in Ruby
Please explain nuances of ||=
What does ||= (or-equals) mean in Ruby?
The definitive list of ||= (OR Equal) threads and pages
Difference between a = a || b and a ||= b
Assignments
A short-circuit (||=) edge case
超級經典面試題: Ruby的 a ||= b (or-equals)是什麼意思呢?

“The man who can drive himself further once the effort gets painful is the man who will win.”

— Roger Bannister, Runner

本文同步發佈於: https://louiswuyj.tw/


上一篇
Day9: Ruby的三種存取控制Public, Private, Protected
下一篇
Day11: Ruby中的Getter及Setter?
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
appletabby
iT邦新手 5 級 ‧ 2019-09-23 23:01:45

這題好像面試會考,筆記。

我要留言

立即登入留言